#include "HeightMap.h"

#include <fstream>

namespace Crows3D
{
   HeightMap::HeightMap(void)
   {
   }

   HeightMap::~HeightMap(void)
   {
   }

   bool HeightMap::LoadHeightmap(Crows3D::Device *dev, std::string filename)
   {
      FILE* file;
	   unsigned int count;
	   BITMAPFILEHEADER bitmapFileHeader;
	   BITMAPINFOHEADER bitmapInfoHeader;
	   int imageSize;
	   unsigned char* bitmapImage = NULL;

      D3D11_BUFFER_DESC bd;
      D3D11_SUBRESOURCE_DATA initData;

      // data for the VB/IB
      VertexPositionTextureNormal *verts;
      unsigned long               *indices;

      // open the file
      if (fopen_s(&file, filename.c_str(), "rb"))
      {
         return false;
      }

      // Read the header
      if (1 != fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, file))
	   {
		   return false;
	   }
      
      // Read the bitmap info
      if (1 != fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, file))
	   {
		   return false;
	   }

      // Save the dimensions
      width  = bitmapInfoHeader.biWidth;
      height = bitmapInfoHeader.biHeight;

      imageSize = width * height * 3;

      // Create the buffer to read file data into
      bitmapImage = new unsigned char[imageSize];

      // Find the beginning of the bitmap data
      fseek(file, bitmapFileHeader.bfOffBits, SEEK_SET);

      // Read in the bitmap image data.
	   count = fread(bitmapImage, 1, imageSize, file);
	   if(count != imageSize)
	   {
		   return false;
	   }

      if (fclose(file))
      {
         return false;
      }




      // OK, lets get the data into something we care about
      int readPos = 0;
      
      // there will be one vertex for each data point
      verts   = new VertexPositionTextureNormal[width * height];
      
      // there will be 6 indices for each "quad" there are [(width-1)*(height-1)] quads
      indices = new unsigned long[(width - 1) * (height - 1) * 6];
      
      // Loop through all our vertices and populate each one
      for (unsigned int i = 0; i < height; ++i)
      {
         for (unsigned int j = 0; j < width; ++j)
         {
            int index = height * i + j;
            verts[index].position = D3DXVECTOR4((float)j, (float)bitmapImage[readPos] / 15.0f, (float)i, 1.0f);
            verts[index].texture  = D3DXVECTOR2((float)j / width, (float)i / height);
            verts[index].normal   = D3DXVECTOR3(0.0f, 1.0f, 0.0f);

            readPos += 3;
         }
      }

      delete [] bitmapImage;


      // Now create the index data for each "quad"
      int index = 0;
      for (unsigned int i = 0; i < height - 1; ++i)
      {
         for (unsigned int j = 0; j < width - 1; ++j)
         {
            indices[index+0] = (i + 0) * height + (j + 0); // j  ,i
            indices[index+1] = (i + 1) * height + (j + 0); // j  ,i+1
            indices[index+2] = (i + 0) * height + (j + 1); // j+1,i
            indices[index+3] = (i + 0) * height + (j + 1); // j+1,i
            indices[index+4] = (i + 1) * height + (j + 0); // j  ,i+1
            indices[index+5] = (i + 1) * height + (j + 1); // j+1,i+1

            index += 6;
         }
      }


      // Set up our vb parameters
      memset(&bd, 0, sizeof(bd));
      bd.Usage = D3D11_USAGE_DEFAULT;                 // write access access by CPU and GPU
      bd.ByteWidth = sizeof(VertexPositionTextureNormal) * 36;             // size is the VERTEX struct * 3
      bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;        // use as a vertex buffer
      bd.CPUAccessFlags = 0;                          // do NOT allow CPU to write in buffer

      // Fill the buffer with some default data
      memset(&initData, 0, sizeof(D3D11_SUBRESOURCE_DATA));
      initData.pSysMem = verts;
	   initData.SysMemPitch = 0;
	   initData.SysMemSlicePitch = 0;

      if (FAILED(dev->GetDevice()->CreateBuffer(&bd, &initData, &vb))) // create the buffer
      {
         return false;
      }
      

      // Set up our ib parameters
      memset(&bd, 0, sizeof(bd));
      bd.Usage = D3D11_USAGE_DEFAULT;                 // write access access by CPU and GPU
      bd.ByteWidth = sizeof(DWORD) * 36;              // size is the VERTEX struct * 3
      bd.BindFlags = D3D11_BIND_INDEX_BUFFER;         // use as a index buffer
      bd.CPUAccessFlags = 0;                          // do NOT allow CPU to write in buffer

      memset(&initData, 0, sizeof(D3D11_SUBRESOURCE_DATA));
      initData.pSysMem = indices;
	   initData.SysMemPitch = 0;
	   initData.SysMemSlicePitch = 0;

      if (FAILED(dev->GetDevice()->CreateBuffer(&bd, &initData, &ib))) // create the buffer
      {
         return false;
      }




      return true;
   }
}